// 实现这个项目的构建任务

/* 说明文档：
1、准备 从gulp解构赋值出src读取文件流方法、dest写入文件流方法、series串行组合任务方法、parallel并行组合任务方法、watch监控文件变化执行任务方法
2、安装gulp - load - plugins用来自动加载gulp插件
3、安装gulp-sass用于编译.scss文件为.css文件；
安装gulp-babel、@babel/core、@babel/preset-env用于编译es6语法为es5语法；
安装ejs模板引擎，准备data数据用来渲染使用模板渲染的html文件
4、 由于开发环境和生成环境都需要以上的编译过程， 三者又互不影响， 所以组成组合任务使用parallel；
由于以上编译过后，在生产构建时 扔需压缩处理，所以以上三种处理文件过后需要写入一个临时文件夹temp中。
5、 安装gulp - useref用来根据注释提取压缩引入html中的css、 js文件，
 之后安装gulp - if区分获取到的不同的文件流.js.html.css文件，
  使用gulp - uglify压缩js文件， 使用gulp - clean - css压缩css文件， 使用gulp - htmlmin压缩html文件，
  这个处理过后文件就可以写入dist文件夹中了。
6、安装gulp-imagemin压缩处理image和font文件类型，public文件夹中其他无需处理的文件直接读取后写入即可
7、安装browser-sync用来在开发环境开启一个服务，实现在开发环境预览页面效果，结合watch实现热更新
8、安装del用来在每一次构建工程之前清除上一次的构建结果及临时文件
9、梳理一下任务组合：
开发环境：先编译compile，再启动服务serve即可
生成环境：先清除上一次的构建结果，再执行 先编译compile，再压缩处理文件useref，与此同时可以执行image、font、extra等文件流的处理任务。
*/

const { src, dest, series, parallel, watch } = require("gulp");
const loadPlugins = require("gulp-load-plugins");
const del = require("del");
const browserSync = require("browser-sync");

const bs = browserSync.create();
const plugins = loadPlugins();

const data = {
    menus: [{
            name: 'Home',
            icon: 'aperture',
            link: 'index.html'
        },
        {
            name: 'Features',
            link: 'features.html'
        },
        {
            name: 'About',
            link: 'about.html'
        },
        {
            name: 'Contact',
            link: '#',
            children: [{
                    name: 'Twitter',
                    link: 'https://twitter.com/w_zce'
                },
                {
                    name: 'About',
                    link: 'https://weibo.com/zceme'
                },
                {
                    name: 'divider'
                },
                {
                    name: 'About',
                    link: 'https://github.com/zce'
                }
            ]
        }
    ],
    pkg: require('./package.json'),
    date: new Date()
}

const styles = () => {
    return src("src/assets/styles/*.scss", { base: "src" })
        .pipe(plugins.sass())
        .pipe(dest("temp"));
};

const script = () => {
    return src("src/assets/scripts/*.js", { base: "src" })
        .pipe(
            plugins.babel({
                presets: ["@babel/preset-env"],
            })
        )
        .pipe(dest("temp"));
};

const pages = () => {
    return src("src/*.html", { base: "src" })
        .pipe(plugins.swig({ data }))
        .pipe(dest("temp"));
};

const images = () => {
    return src("src/assets/images/**", { base: "src" })
        .pipe(plugins.imagemin())
        .pipe(dest("dist"));
};

const fonts = () => {
    return src("src/assets/fonts/**", {
            base: "src",
        })
        .pipe(plugins.imagemin())
        .pipe(dest("dist"));
};

const extra = () => {
    return src("public/**", { base: "public" }).pipe(dest("dist"));
};

const serve = () => {
    watch("src/assets/styles/*.scss", styles);
    watch("src/assets/scripts/*.js", script);
    watch("src/*.html", pages);

    watch(
        ["src/assets/images/**", "src/assets/fonts/**", "public/**"],
        bs.reload
    );
    bs.init({
        notify: false,
        port: 2020,
        server: {
            baseDir: ["temp", "src", "public"],
            routes: {
                "/node_modules": "node_modules",
            },
        },
    });
};

const useref = () => {
    return src("temp/*.html", { base: "temp" })
        .pipe(plugins.useref({ searchPath: ["dist", "."] }))
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(
            plugins.if(
                /\.html$/,
                plugins.htmlmin({
                    collapseWhitespace: true,
                    minifyCSS: true,
                    minifyJS: true,
                })
            )
        )
        .pipe(dest("dist"));
};

const clean = () => {
    return del("temp", "dist");
};

const compile = parallel(script, styles, pages);

const build = series(
    clean,
    parallel(series(compile, useref), images, fonts, extra)
);

const develop = series(compile, serve);

module.exports = {
    build,
    clean,
    develop,
};